package com.sh.ndt.common;

import java.net.InetAddress;
import java.text.DecimalFormat;
import java.net.UnknownHostException;
import java.util.ArrayList;

import org.apache.log4j.Logger;

import com.sh.ndt.common.Constants.DecimalPrecision;

public class CommonUtil {
	private static final Logger LOGGER = Logger.getLogger(CommonUtil.class);

	public static String RemoveSpecialCharacters(String textToFormat) {
		String pattern = "[^A-Za-z0-9]";
		return textToFormat.replaceAll(pattern, "");
	}

	public static String getHostname() {
		String hostname = "";
		try {
			hostname = InetAddress.getLocalHost().getHostName();
		} catch (UnknownHostException e) {
			hostname = "unknown";
		}

		return hostname;
	}

	public static String convertStackTraceToString(Exception e) {
		StringBuffer s = new StringBuffer();

		s.append("\n --------------------------- \n");
		for (StackTraceElement ste : e.getStackTrace()) {
			s.append(ste.toString() + "\n");
		}
		s.append(" --------------------------- \n");
		return s.toString();
	}

	public static String getFormatedNumberOfPrecision(
			DecimalPrecision decimalPlaces, double number) {
		String format = "#.##";
		switch (decimalPlaces) {
		case ZERO:
			format = "#";
			break;
		case ONE:
			format = "#.#";
			break;
		case TWO:
			format = "#.##";
			break;
		case THREE:
			format = "#.###";
			break;
		case FOUR:
			format = "#.####";
			break;
		case FIVE:
			format = "#.#####";
			break;
		case SIX:
			format = "#.######";
			break;
		case SEVEN:
			format = "#.#######";
			break;
		case EIGHT:
			format = "#.########";
			break;
		case NINE:
			format = "#.#########";
			break;
		case TEN:
			format = "#.##########";
			break;
		}

		//
		// LOGGER.debug("Format No : " + number + " for : " +
		// decimalPlaces.ordinal() + " decimal(s), pattern : " + format +
		// ", out put : " + Double.parseDouble(new
		// DecimalFormat(format).format(number)));
		//
		return new DecimalFormat(format).format(number);
	}

	public static void dumpThreadHierarchy() {
		LOGGER.debug("\n\n-----------------------------------------------------");
		LOGGER.debug("CURRENT THREAD IS :" + Thread.currentThread().getName());
		listThreads(findRootThread(), " : ");
		LOGGER.debug("\n-----------------------------------------------------\n\n");
	}

	//
	// from Stackoverflow.com
	//
	public static ThreadGroup findRootThread() {
		ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
		ThreadGroup parent;
		while ((parent = rootGroup.getParent()) != null) {
			rootGroup = parent;
		}
		return rootGroup;
	}

	public static void listThreadChain() {
		LOGGER.debug("------ THREAD CHAIN INFO ------ ");
		LOGGER.debug("CURRENT THREAD :" + Thread.currentThread().getName());
		ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
		ThreadGroup parent;
		ArrayList<String> threadlist = new ArrayList<String>();
		threadlist.add(Thread.currentThread().getName());
		while ((parent = rootGroup.getParent()) != null) {
			rootGroup = parent;
			threadlist.add(parent.getName());
		}
		int numThreadsInChain = threadlist.size();
		for (int i = 0; i < numThreadsInChain; i++) {
			LOGGER.debug(threadlist.get(i));
			if (i < (numThreadsInChain - 1)) {
				LOGGER.debug("  | ");
				LOGGER.debug("  V ");
			}
		}
		LOGGER.debug("-------END THREAD CHAIN INFO---");
	}

	//
	// from stackoverflow.com
	//
	public static void listThreads(ThreadGroup group, String indent) {

		LOGGER.debug(indent + "Group[" + group.getName() + ":"
				+ group.getClass() + "]");
		int nt = group.activeCount();
		Thread[] threads = new Thread[nt * 2 + 10]; // nt is not accurate
		nt = group.enumerate(threads, false);

		// List every thread in the group
		for (int i = 0; i < nt; i++) {
			Thread t = threads[i];
			LOGGER.debug(indent + "  Thread[" + t.getName() + ":"
					+ t.getClass() + "]");
		}

		// Recursively list all subgroups
		int ng = group.activeGroupCount();
		ThreadGroup[] groups = new ThreadGroup[ng * 2 + 10];
		ng = group.enumerate(groups, false);

		for (int i = 0; i < ng; i++) {
			listThreads(groups[i], indent + "  ");
		}
	}

	//
	// memory usage information
	//

	public static void printMemoryInfo(boolean uselogger) {
		if (uselogger == true) {
			LOGGER.debug(CommonUtil.listMemoryInfo());
		} else {
			System.err.println(CommonUtil.listMemoryInfo());
		}
	}

	public static String listMemoryInfo() {
		// LOGGER is log4j Logger instance

		Runtime runtimeObj = Runtime.getRuntime();

		// Total number of processors or cores available to the JVM
		int noOfProcessors = runtimeObj.availableProcessors();

		// Total memory currently available for JVM
		long totalMemory = runtimeObj.totalMemory();
		Float totalMemoryMB = (float) (totalMemory) / (1024 * 1024);
		Float totalMemoryGB = (float) totalMemory / (1024 * 1024 * 1024);

		// maxMemory() method returns Long.MAX_VALUE if there is no inherent
		// limit
		// Maximum amount of memory the JVM will attempt to use
		long maxMemory = runtimeObj.maxMemory();
		Float maxMemoryMB = (float) maxMemory / (1024 * 1024);
		Float maxMemoryGB = (float) maxMemory / (1024 * 1024 * 1024);

		// Total amount of free memory available to the JVM
		long freeMemory = runtimeObj.freeMemory();
		Float freeMemoryMB = (float) freeMemory / (1024 * 1024);
		Float freeMemoryGB = (float) freeMemory / (1024 * 1024 * 1024);

		// Get Used Memory
		long usedMemory = totalMemory - freeMemory;
		Float usedMemoryMB = (float) usedMemory / (1024 * 1024);
		Float usedMemoryGB = (float) usedMemory / (1024 * 1024 * 1024);

		String message = "\n-------------------------------------------\n"
				+ "System Stats" + "\n" + "Number of Processors       : "
				+ noOfProcessors
				+ "\n"
				+ "Total JVM Memory           : "
				+ totalMemory
				+ "\n"
				+ "Max Memory                 : "
				+ maxMemory
				+ "\n"
				+ "Free Memory                : "
				+ freeMemory
				+ "\n"
				+ "Used Memory                : "
				+ usedMemory
				+ "\n"

				+ "Total JVM Memory MB        : "
				+ totalMemoryMB.toString()
				+ "\n"
				+ "Max Memory       MB        : "
				+ maxMemoryMB.toString()
				+ "\n"
				+ "Free Memory      MB        : "
				+ freeMemoryMB.toString()
				+ "\n"
				+ "Used Memory      MB        : "
				+ usedMemoryMB.toString()
				+ "\n"

				+ "Total JVM Memory GB        : "
				+ totalMemoryGB.toString()
				+ "\n"
				+ "Max Memory       GB        : "
				+ maxMemoryGB.toString()
				+ "\n"
				+ "Free Memory      GB        : "
				+ freeMemoryGB.toString()
				+ "\n"
				+ "Used Memory      GB        : "
				+ usedMemoryGB.toString()
				+ "\n"
				+ "-------------------------------------------\n";

		return message;

		// LOGGER.debug ("Maximum memory (bytes): " +
		// (maxMemory == Long.MAX_VALUE ? "no limit" : maxMemory));

	}
}
